package com.sina.shop.manage.service.address;

import com.sina.shop.core.exception.client.DataException;
import com.sina.shop.core.exception.server.CreateException;
import com.sina.shop.core.exception.server.ResourceExistsException;
import com.sina.shop.core.exception.server.UpdateException;
import com.sina.shop.domain.address.Address;
import com.sina.shop.domain.address.Status;
import com.sina.shop.domain.admin.Admin;
import com.sina.shop.manage.dao.address.AddressManageDao;
import com.sina.shop.manage.dao.admin.AdminManageDao;
import com.sina.shop.service.ShopDataSourceService;
import com.sina.shop.util.Assert;
import com.sina.shop.util.ResultCode;
import com.sina.shop.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

import static com.sina.shop.service.ServiceConstant.SHOP_TX;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * 段浩杰   2018-01-03-16:35
 */
@Service("addressManageService")
public class AddressManageServiceImpl extends ShopDataSourceService implements AddressManageService {

    @Autowired
    @Qualifier("addressManageDao")
    private AddressManageDao addressManageDao;

    @Autowired
    @Qualifier("adminManageDao")
    private AdminManageDao adminManageDao;

    @Override
    @Transactional(value = SHOP_TX, readOnly = true, isolation = Isolation.READ_COMMITTED)
    public Address getAddressByName(String name) {
        return addressManageDao.getAddressByName(name);
    }

    @Override
    @Transactional(value = SHOP_TX, readOnly = true, isolation = Isolation.READ_COMMITTED)
    public Address getAddressById(Long id) {
        return addressManageDao.get(Address.class, id);
    }

    @Override
    @Transactional(value = SHOP_TX, isolation = Isolation.REPEATABLE_READ)
    public int deleteAddress(Long id) throws DataException, UpdateException {
        Address address = addressManageDao.get(Address.class, id);
        Assert.assertNotNull(address, "Address[id=%s] not exists", address.getId());

        try {
            return addressManageDao.deleteAddress(id);
        } catch (DataAccessException e) {
            LOG.error(" {} delete Address error.", Address.class, e);
            throw new UpdateException(ResultCode.dataAccessError, e.getMessage(), e);
        }
    }

    @Override
    @Transactional(value = SHOP_TX, isolation = Isolation.READ_COMMITTED)
    public Address saveAddress(Address address) throws CreateException, ResourceExistsException, DataException {
        try {
            if (!StringUtils.isEmpty(address.getStatus())) {
                if (address.getStatus() == Status.USE) {
                    updateAddressStatus(address.getAdmin().getId());
                }
            }
            addressManageDao.save(address);
            addressManageDao.flush();
            return address;
        } catch (DataAccessException e) {
            LOG.error(" {} save Address error.", Address.class, e);
            throw new UpdateException(ResultCode.dataAccessError, e.getMessage(), e);
        }
    }

    @Override
    @Transactional(value = SHOP_TX, isolation = Isolation.REPEATABLE_READ)
    public Address updateAddress(Address address) throws UpdateException, DataException {
        Address a = addressManageDao.get(Address.class, address.getId());
        Assert.assertNotNull(a, "Address[id=%s] not exists", address.getId());

        try {
            a = updateAddressFiled(address, a);
            addressManageDao.flush();

            return a;
        } catch (DataAccessException e) {
            LOG.error(" {} update Address error.", Address.class, e);
            throw new UpdateException(ResultCode.dataAccessError, e.getMessage(), e);
        }

    }

    private Address updateAddressFiled(Address oldAddress, Address newAddress) throws CreateException {

        if (!StringUtils.isEmpty(oldAddress.getProvince())) {
            newAddress.setProvince(oldAddress.getProvince());
        }
        if (!StringUtils.isEmpty(oldAddress.getCity())) {
            newAddress.setCity(oldAddress.getCity());
        }
        if (!StringUtils.isEmpty(oldAddress.getCountry())) {
            newAddress.setCountry(oldAddress.getCountry());
        }
        if (!StringUtils.isEmpty(oldAddress.getStreet())) {
            newAddress.setStreet(oldAddress.getStreet());
        }
        if (!StringUtils.isEmpty(oldAddress.getZipCode())) {
            newAddress.setZipCode(oldAddress.getZipCode());
        }
        if (!StringUtils.isEmpty(oldAddress.getStatus())) {
            if (oldAddress.getStatus() == Status.USE) {
                updateAddressStatus(newAddress.getAdmin().getId());
                //updateAddressStatus(oldAddress.getAdmin() != null ? oldAddress.getAdmin().getId() : null);
            }
            newAddress.setStatus(oldAddress.getStatus());
        }
        if (oldAddress.getCreateTime() != null) {
            newAddress.setCreateTime(oldAddress.getCreateTime());
        }
        if (oldAddress.getAdmin() != null) {
            newAddress.setAdmin(oldAddress.getAdmin());
        }
        return newAddress;
    }

    @Override
    @Transactional(value = SHOP_TX, readOnly = true, isolation = Isolation.READ_COMMITTED)
    public List<Map<String, Object>> getAddressList(Address address, Long[] count) {

        Admin admin = null;

        if (address.getAdmin() != null && !StringUtils.isEmpty(address.getAdmin().getAccount())) {

            admin = adminManageDao.getAdmin(address.getAdmin().getAccount());


            if (admin == null) {
                admin = new Admin();
            }
        }

        address.setAdmin(admin);

        if (count != null && count.length > 0) {
            count[0] = addressManageDao.getAddressCount(address);
        }

        return addressManageDao.getAddressList(address);
    }

    @Override
    @Transactional(value = SHOP_TX, isolation = Isolation.REPEATABLE_READ)
    public int updateAddressStatus(Long aid) throws UpdateException {
        try {
            return addressManageDao.updateAddressStatus(aid);
        } catch (DataAccessException e) {
            LOG.error(" {} update Address error.", Address.class, e);
            throw new UpdateException(ResultCode.dataAccessError, e.getMessage(), e);
        }
    }
}
